(** An functional style interface to programming graphics with GTK*)

type color = Red | Blue | Black | White ;;

let scale = ref 0.;;
let height = 480;;
let width = 480;;

(* Prepare a bunch of GTK trash *)
let locale  = GtkMain.Main.init ();; 
let window = GWindow.window ~title:"OCAML Graphics with GTK" () ;;
let drawing_area = GMisc.drawing_area 
		     ~packing:window#add 
		     ~height:height
		     ~width:width 
		     ();; 
let drawing = ref (
  drawing_area#misc#realize ();
  new GDraw.drawable (drawing_area#misc#window)
)
;;

(* Set the infos *)
let init_graphics (maxspeed : Vector.speed) this_drawing =
  
  drawing := this_drawing;
  
  (* Determine at which scale to draw *)
  let
    sizex =  width 
  and
    sizey =  height
  in
  let
    minsize = 
    if sizex > sizey then sizey else sizex
  in
    scale := (float_of_int (minsize/2)) /. maxspeed 
    ;
    
    (* Some standard stuff to do *)
    (!drawing)#set_foreground `WHITE;
    (!drawing)#set_foreground `BLACK;
    (!drawing)#set_line_attributes ~width:2 ();
;;


let get_center () = (480/2,480/2) ;; 
let set_line_width n = (!drawing)#set_line_attributes ~width:n ()
;;
let set_color color =
  match color with
      Blue -> (!drawing)#set_foreground (`NAME "Blue")
    | Red ->   (!drawing)#set_foreground (`NAME "Red")
    | Black -> (!drawing)#set_foreground `BLACK
    | White -> (!drawing)#set_foreground `WHITE
;;


let scale_to_int x = 
  truncate (x *. !scale)
;;

let point_to_ints (Vector.Pt (x,y)) = 
  ( scale_to_int x,scale_to_int y)
;; 


let  adjust_y y = height - y ;;

let draw_vector startpoint direction =
  let 
    (xc,yc) = get_center ()
  and
    (x1,y1) =  point_to_ints (Vector.point_of_vector startpoint) 
  and
    (x2,y2) =  point_to_ints (Vector.point_of_vector direction)
  in
    (!drawing)#line ~x:(xc + x1) ~y:(adjust_y (yc + y1))  ~x:(xc + x1 + x2) ~y:(adjust_y (yc +y1 + y2))
;;

let draw_point vector =
  let 
    (xc,yc) = get_center ()
  and
    (x1,y1) =  point_to_ints (Vector.point_of_vector vector) 
  in
    (!drawing)#point ~x:(xc + x1) ~y:(adjust_y (yc + y1))  
;;

let draw_line firstpoint secondpoint =
  let 
    (xc,yc) = get_center ()
  and
    (x1,y1) =  point_to_ints (Vector.point_of_vector firstpoint) 
  and
    (x2,y2) =  point_to_ints (Vector.point_of_vector secondpoint)
  in
    (!drawing)#line ~x:(xc + x1) ~y:(adjust_y (yc + y1))  ~x:(xc +  x2) ~y:(adjust_y (yc + y2))
;;

let draw_circle center radius =
  let 
    (xc,yc) = get_center ();
  and
    int_radius = (scale_to_int radius) 
  in
  let
    diameter = int_radius * 2
  in
    (!drawing)#arc ~x:(xc - int_radius) ~y:((adjust_y yc) - int_radius) ~width:(diameter ) ~height:(diameter) ()
;;

let draw_area center radius =
  let 
    (xc,yc) = get_center ();
  and
    int_radius = (scale_to_int radius) 
  in
  let
    diameter = int_radius * 2
  in
    (!drawing)#rectangle 
      ~filled:true
      ~x:(xc - int_radius) 
      ~y:((adjust_y yc) - int_radius) 
      ~width:(diameter ) 
      ~height:(diameter) ()
;;


